﻿#include "SettingManager.h"

#include <fast_io/fast_io.h>
#include <fast_io/fast_io_device.h>

#include "../../Utils/Utils.h"
#include "../../Utils/Logger.h"
#include "../../Memory/GameData.h"

#include <json/nlohmannjson.h>

#include "../Config/ConfigManager.h"
#include "../Commands/Commands/TranslateCommand.h"

uint32_t SettingManager::languageget{};

std::u8string SettingManager::language{};  // zh-cn, en-us etc.

std::u8string SettingManager::lastConfig{};  // zh-cn, en-us etc.

std::map<char8_t, std::u8string> SettingManager::autotextbindings{};

void SettingManager::exit() {
	const std::u8string settingfile{fast_io::u8concat(Utils::Utils::RoamingStateFold, u8"setting.h")};
	try {
		nlohmann::json SettingObj;
		SettingObj["language"] = *reinterpret_cast<std::string*>(&language);
		SettingObj["default config"] = *reinterpret_cast<std::string*>(&configMgr.currentConfig);
		SettingObj["transl_appid"] = appid;
		SettingObj["transl_key"] = *reinterpret_cast<std::string*>(&key);
		SettingObj["transl_local_from"] = *reinterpret_cast<std::string*>(&local_from);
		SettingObj["transl_local_to"] = *reinterpret_cast<std::string*>(&local_to);
		SettingObj["transl_server_from"] = *reinterpret_cast<std::string*>(&server_from);
		SettingObj["transl_server_to"] = *reinterpret_cast<std::string*>(&server_to);
		SettingObj["autotextbindings"] = *reinterpret_cast<std::map<char, std::string>*>(&autotextbindings);

		fast_io::u8obuf_file of(settingfile, fast_io::open_mode::text);
		auto temp = SettingObj.dump();
		println(of, std::move(*reinterpret_cast<std::u8string*>(&temp)));
	} catch (const fast_io::error& e) {
		Logger::LogC(LogGrade::warning, u8"Setting Load Exception! : ", e);
	} catch (std::exception& e) {
		Logger::LogC(LogGrade::warning, u8"Setting Load Exception! : ", fast_io::mnp::os_c_str(reinterpret_cast<const char8_t*>(e.what())));
	}
}

bool SettingManager::load() {
	const std::u8string settingfile{fast_io::u8concat(Utils::Utils::RoamingStateFold, u8"setting.h")};
	try {
		fast_io::u8obuf_file of(settingfile, fast_io::open_mode::text | fast_io::open_mode::noreplace);
		// write
		println(of, u8R"({"autotextbindings":[],"default config":"default","language":"en_US","transl_appid":0,"transl_com_from":"auto","transl_com_to":"en","transl_key":"","transl_mod_from":"auto","transl_mod_to":"en"})");
	} catch (const fast_io::error&) {
	}
	try {
		nlohmann::json SettingObj = nlohmann::json::parse(fast_io::native_file_loader{fast_io::u8concat(Utils::Utils::RoamingStateFold, u8"setting.h")});
		std::string lan = SettingObj.at("language").get<std::string>();
		language = std::move(*reinterpret_cast<std::u8string*>(&lan));
		std::string curconf = SettingObj.at("default config").get<std::string>();
		using std::operator""s;
		if (curconf.empty())
			lastConfig = u8"default"s;
		else
			lastConfig = std::move(*reinterpret_cast<std::u8string*>(&curconf));

		appid = SettingObj.at("transl_appid").get<std::uint_least64_t>();
		auto sbkey = SettingObj.at("transl_key").get<std::string>();
		key = std::move(*reinterpret_cast<std::u8string*>(&sbkey));
		auto sblocfrom = SettingObj.at("transl_local_from").get<std::string>();
		local_from = std::move(*reinterpret_cast<std::u8string*>(&sblocfrom));
		auto sblocto = SettingObj.at("transl_local_to").get<std::string>();
		local_to = std::move(*reinterpret_cast<std::u8string*>(&sblocto));
		auto sbserfrom = SettingObj.at("transl_server_from").get<std::string>();
		server_from = std::move(*reinterpret_cast<std::u8string*>(&sbserfrom));
		auto sbserto = SettingObj.at("transl_server_to").get<std::string>();
		server_to = std::move(*reinterpret_cast<std::u8string*>(&sbserto));
		auto bindings = SettingObj.at("autotextbindings").get<std::map<char, std::string>>();
		autotextbindings = std::move(*reinterpret_cast<std::map<char8_t, std::u8string>*>(&bindings));

		getLanguage();
	} catch (const std::exception&) { // Garbage string
		//Logger::LogC(LogGrade::warning, u8"Setting Load Failed! : ", fast_io::mnp::os_c_str(reinterpret_cast<const char8_t*>(e.what())));
		using std::operator""s;
		language = u8"en_US"s;
		lastConfig = u8"default"s;
		languageget = 0;
		appid = 0;
		key.clear();
		local_from = u8"auto"s;
		local_to = u8"en"s;
		server_from = u8"auto"s;
		server_to = u8"en"s;
		autotextbindings.clear();
		return true;
	}

	return true;
}

void SettingManager::getLanguage() noexcept {
	using std::operator""sv;
	if (language == u8"en_US"sv)
		languageget = 0;
	else if (language == u8"zh_CN"sv) 
		languageget = 1;
	else if (language == u8"zh_HK"sv || language == u8"zh_SG"sv || language == u8"zh_TW"sv || language == u8"zh_ZA"sv) 
		languageget = 2;
	else if (language == u8"ja_JP"sv) 
		languageget = 3;
	else {
		language = u8"en_US"sv;  // default
		languageget = 0;
	}
}
